// ValidationAspects
// Written by Mike Saunders
// Released under Microsoft Public License (Ms-PL)
using System;
using NUnit.Framework;
using ValidationAspects;
using ValidationAspects.Exceptions;
using ValidationAspects.Sdk;

namespace TestValidationAspects.Sdk
{
	[TestFixture]
	public class TestNumericValidatorFactoryBase
	{
		[Test]
		public void Test_Create_if_T_is_not_supported_for_conversion()
		{
			Test.Throws<UnsupportedValidationException>(() => new MockFactory().Create<TestNumericValidatorFactoryBase>(),
			                                            string.Format("Comparison between [type:{0}] and [type{1}] is not supported for numeric validators", typeof(double), GetType()));
		}

		[Test]
		public void Test_Create_returns_a_validator_that_executes_the_provided_validate_action()
		{
			MockFactory factory = new MockFactory();
			IValidationContext context = new MockValidationContext();

			IValidator<double> validator = factory.Create<double>();
			validator.Invoke(1, context);

			Assert.AreEqual(1, factory.Value);
			Assert.AreSame(context, factory.Context);
		}

		[Test]
		public void Test_Create_returns_a_validator_that_executes_the_provided_validate_action_for_nullable_types()
		{
			MockFactory factory = new MockFactory();
			IValidationContext context = new MockValidationContext();

			IValidator<double?> validator = factory.Create<double?>();
			validator.Invoke(1, context);

			Assert.AreEqual(1, factory.Value);
			Assert.AreSame(context, factory.Context);
		}

		[Test]
		public void Test_Create_with_supported_types()
		{
			MockFactory factory = new MockFactory();

			factory.Create<double>();
			factory.Create<decimal>();
			factory.Create<int>();
			factory.Create<long>();
			factory.Create<float>();
			factory.Create<short>();
			factory.Create<char>();
			factory.Create<byte>();
			factory.Create<uint>();
			factory.Create<ulong>();
			factory.Create<ushort>();
			factory.Create<sbyte>();

			factory.Create<double?>();
			factory.Create<decimal?>();
			factory.Create<int?>();
			factory.Create<long?>();
			factory.Create<float?>();
			factory.Create<short?>();
			factory.Create<char?>();
			factory.Create<byte?>();
			factory.Create<uint?>();
			factory.Create<ulong?>();
			factory.Create<ushort?>();
			factory.Create<sbyte?>();
		}

		#region Mocks
		public class MockFactory : NumericValidatorFactoryBase
		{
			public object Value { get; set; }
			public object Context { get; set; }

			#region Overrides of NumericValidatorFactoryBase
			protected override Action<T, IValidationContext> GetValidateAction<T>(Func<T, double, int> compareFunc)
			{
				Enforce.IsNotNull(compareFunc, "compareFunc");
				return (v, c) =>
				       {
				       	Value = v;
				       	Context = c;
				       };
			}
			#endregion
		}
		#endregion
	}
}